﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.Linq;

namespace BrettM.Data.Linq
{
    public static class SecurityExtensions
    {

        public static IEnumerable<TElement> ExecAs<TElement>(this IQueryable<TElement> query, System.Data.Linq.DataContext context, string username)
        {

            return new SecurityAdapter<TElement>(query, context, username);

        }

    }

    public class SecurityAdapter<T> : IEnumerable<T>
    {

        private readonly IQueryable<T> _query;
        private readonly DataContext _context;
        private readonly string _username;
        private readonly List<T> _results = new List<T>();
        private bool _hasInitialized;



        public SecurityAdapter(IQueryable<T> query, System.Data.Linq.DataContext context, string username)
        {

            _query = query;
            _context = context;
            _username = username;
        }



        public IEnumerator<T> GetEnumerator()
        {

            if (!_hasInitialized)
            {

                _hasInitialized = true;


                // This is called when they enumerate this collection. We 
                // ask the DataContext to generate the query, then we modify it, 
                // execute it, and tell the DataContext to load the results
                var command = _context.GetCommand(_query);
                var wasOpen = command.Connection.State == ConnectionState.Open;

                try
                {
                    command.CommandText =
                        "-- " + _username + " ROCKS" + Environment.NewLine
                        + command.CommandText + Environment.NewLine
                        + "-- " + _username + " ROCKS" + Environment.NewLine;

                    if (!wasOpen)
                    {
                        command.Connection.Open();
                    }

                    var reader = command.ExecuteReader();
                    _results.AddRange(_context.Translate<T>(reader).ToList());
                }
                finally
                {
                    if (!wasOpen)
                    {
                        command.Connection.Close();
                    }
                }
            }
            return _results.GetEnumerator();
        }



        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}
